package com.caiyouxi.pay.payment.weixin.utils;

import com.caiyouxi.pay.payment.weixin.exception.ResponseStatusException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * 简单http请求工具类
 * 
 * @author yiqifendou
 * 
 */
@SuppressWarnings("all")
public class HttpUtils {
	
	/**
	 * 以get方式发送请求
	 * 
	 * @param url
	 *            请求地址
	 * @param params
	 *            参数(也可直接在url上拼接),可为null
	 * @param paramsCharset
	 *            参数编码,可为null,nul时默认utf-8
	 * @param resultCharset
	 *            响应实体编码,可为null,nul时默认utf-8
	 * @return
	 * @throws IOException 
	 * @throws ResponseStatusException
	 * @throws Exception  
	 */
	public static String requestByGet(String url,
			Map<String, String> params, String paramsCharset,
			String resultCharset) throws IOException, ResponseStatusException {
		HttpClient client = null;
		InputStream is = null;
		BufferedInputStream bf = null;
		ByteArrayOutputStream tempOut = null;
		// 拼接参数
		if (params != null && params.size() != 0) {
			if (paramsCharset == null || "".equals(paramsCharset)) {
				paramsCharset = "UTF-8";
			}
			url = url + "?";
			String paramsStr = "";
			Set<String> keySet = params.keySet();
			for (String key : keySet) {
				try {
					paramsStr = paramsStr + key + "="
							+ URLEncoder.encode(params.get(key), paramsCharset)
							+ "&";
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
					throw e;
				}
			}
			paramsStr = paramsStr.substring(0, paramsStr.length()-1);
			url = url + paramsStr;
		}
		try {
			// 创建一个默认的浏览器,即http客户端
			client = new DefaultHttpClient();
			//设置请求超时
			client.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 10000);
			//设置连接超时
			client.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,10000);
			// 输入地址
			HttpGet httpGet = new HttpGet(url);
			// 敲回车,执行get请求
			HttpResponse response = client.execute(httpGet);
			// 请求成功
			if (response.getStatusLine().getStatusCode() == 200) {
				// 获取响应实体对应的流
				HttpEntity entity = response.getEntity();
				is = entity.getContent();
				bf = new BufferedInputStream(is);
				// 内存流，用于临时存放响应体中的内容
				tempOut = new ByteArrayOutputStream();
				byte[] bytes = new byte[1024];
				int len = 0;
				while ((len = bf.read(bytes, 0, bytes.length)) != -1) {
					tempOut.write(bytes, 0, len);
				}
				if (resultCharset == null) {
					resultCharset = "UTF-8";
				}
				return tempOut.toString(resultCharset);
			}else{
				throw new ResponseStatusException("http响应状态异常,响应行:"+response.getStatusLine());
			}
		} catch (ConnectTimeoutException e) {  
	        System.out.println("连接超时 (请求超时)");  
	        e.printStackTrace();
	        throw e;
	    } catch (SocketTimeoutException e) {  
	        System.out.println("响应超时");  
	        e.printStackTrace();
	        throw e;
	    } catch (ClientProtocolException e) {
			e.printStackTrace();
			throw e;
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
					throw e;
				}
			}
			if (bf != null) {
				try {
					bf.close();
				} catch (IOException e) {
					e.printStackTrace();
					throw e;
				}
			}
			if (tempOut != null) {
				try {
					tempOut.close();
				} catch (IOException e) {
					e.printStackTrace();
					throw e;
				}
			}
			//关闭连接释放资源
			client.getConnectionManager().shutdown();
		}
	}
	
	/**
	 * get方法发送请求,参数编码和响应记过编码都是utf-8
	 * @param url
	 * @return
	 * @throws IOException
	 * @throws ResponseStatusException
	 */
	public static String requestByGet(String url) throws IOException, ResponseStatusException {
		return requestByGet(url, null, null, null);
	}   

	/**
	 * HttpClient框架发送post请求
	 * 
	 * @param url
	 *            请求url
	 * @param params
	 *            请求参数
	 * @param paramsCharset
	 *            请求参数编码 可为null,nul时默认utf-8
	 * @param resultCharset
	 *            返回内容编码 可为null,nul时默认utf-8
	 * @return
	 * @throws ResponseStatusException
	 */
	public static String requestByPost(String url,
			Map<String, String> params, String paramsCharset,
			String resultCharset) throws IOException, ResponseStatusException {
		HttpClient client = null;
		InputStream is = null;
		BufferedInputStream bf = null;
		ByteArrayOutputStream tempOut = null;
		try {
			// 创建一个默认的浏览器
			client = new DefaultHttpClient();
			//设置请求超时
			client.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 10000);
			//设置连接超时
			client.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,10000);
			HttpPost httpPost = new HttpPost(url);
			// 要提交的数据实体中的参数集合
			List<NameValuePair> parameters = new ArrayList<NameValuePair>();
			if (params != null && params.size() != 0) {
				for (String key : params.keySet()) {
					parameters.add(new BasicNameValuePair(key, params.get(key)));
				}
			}
			if (paramsCharset == null || "".equals(paramsCharset)) {
				paramsCharset = "UTF-8";
			}
			// 设置请求实体为表单实体
			httpPost.setEntity(new UrlEncodedFormEntity(parameters,
					paramsCharset));
			HttpResponse response = client.execute(httpPost);
			if (response.getStatusLine().getStatusCode() == 200) {
				// 获取响应实体对应的流
				HttpEntity entity = response.getEntity();
				is = entity.getContent();
				bf = new BufferedInputStream(is);
				// 内存流，用于临时存放响应体中的内容
				tempOut = new ByteArrayOutputStream();
				byte[] bytes = new byte[1024];
				int len = 0;
				while ((len = bf.read(bytes, 0, bytes.length)) != -1) {
					tempOut.write(bytes, 0, len);
				}
				if (resultCharset == null || "".equals(resultCharset)) {
					resultCharset = "UTF-8";
				}
				return tempOut.toString(resultCharset);
			}else{
				throw new ResponseStatusException("http响应状态异常,响应行:"+response.getStatusLine());
			}
		} catch (ConnectTimeoutException e) {  
	        System.out.println("连接超时 (请求超时)");  
	        e.printStackTrace();
	        throw e;
	    } catch (SocketTimeoutException e) {  
	        System.out.println("响应超时");  
	        e.printStackTrace();
	        throw e;
	    } catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			throw e;
		} catch (ClientProtocolException e) {
			e.printStackTrace();
			throw e;
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
					throw e;
				}
			}
			if (bf != null) {
				try {
					bf.close();
				} catch (IOException e) {
					e.printStackTrace();
					throw e;
				}
			}
			if (tempOut != null) {
				try {
					tempOut.close();
				} catch (IOException e) {
					e.printStackTrace();
					throw e;
				}
			}
			//关闭连接释放资源
			client.getConnectionManager().shutdown();
		}
	}
	
	/**
	 * get方式发送请求，请求参数编码和响应结果编码都是utf-8
	 * @param url
	 * @param params
	 * @param paramsCharset
	 * @param resultCharset
	 * @return
	 * @throws IOException
	 * @throws ResponseStatusException
	 */
	public static String requestByPost(String url,
			Map<String, String> params) throws IOException, ResponseStatusException {
		return requestByPost(url, params, null, null);
	}
	
	
	/**
	 * 通过流传递数据
	 * Description: <br>
	 * 
	 * @param url
	 * @param data
	 * @return
	 * @throws IOException 
	 * @see
	 */
    public static String requestByStream(String url,String data) throws IOException{
        HttpURLConnection httpConn = null;
        InputStream is = null;
        try
        {
            httpConn = (HttpURLConnection)new URL(url).openConnection();
            httpConn.setRequestMethod("POST");
            httpConn.setDoInput(true);
            httpConn.setDoOutput(true);
            OutputStream out = httpConn.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
            osw.write(data);
            osw.flush();
            osw.close();
            out.close();
            is = httpConn.getInputStream();
            return InputStreamUtils.InputStreamTOString(is);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            throw e;
        }
        finally
        {
            if(is!=null){
                try
                {
                    is.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
    
    /**
     * 用于微信上传媒体文件
     * Description: <br>
     * 
     * @param url
     * @param f
     * @return
     * @throws ResponseStatusException
     * @throws IOException 
     * @see
     */
    public static String uploadMedia(String url,File f) throws ResponseStatusException, IOException {
        HttpClient httpclient = new DefaultHttpClient();  
        String result = null;
        try {  
            HttpPost httppost = new HttpPost(url);   
            FileBody fb = new FileBody(f);  
            MultipartEntity reqEntity = new MultipartEntity();  
            reqEntity.addPart("media", fb);// upload为请求后台的File upload属性  
            httppost.setEntity(reqEntity);  
            HttpResponse response = httpclient.execute(httppost);  
            int statusCode = response.getStatusLine().getStatusCode();  
            if (statusCode == HttpStatus.SC_OK) {  
                HttpEntity respEntity = response.getEntity();  
                // httpclient自带的工具类读取返回数据  
                //EntityUtils.toString(respEntity)只能执行一次，执行第二次将返回空
                result = EntityUtils.toString(respEntity);   
            }  else{
                throw new ResponseStatusException("http响应状态异常,响应行:"+response.getStatusLine());
            }
        } catch (IOException e) {  
            e.printStackTrace();
            throw e;
        } finally {   
            try {  
                httpclient.getConnectionManager().shutdown();  
            } catch (Exception ignore) {  
            }  
        }  
        return result;
    }
    
    public static String getUrl(String url){
        String result = null;
        try {
            // 根据地址获取请求
            HttpGet request = new HttpGet(url);
            // 获取当前客户端对象
            HttpClient httpClient = new DefaultHttpClient();
            // 通过请求对象获取响应对象
            HttpResponse response = httpClient.execute(request);
            
            // 判断网络连接状态码是否正常(0--200都数正常)
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                result= EntityUtils.toString(response.getEntity());
            } 
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result;
    }
    
    
	
}



